# coding: utf-8
# @Author: cyl
# @File: 05内置函数.py
# @Time: 2024/07/07 09:55:42
import math
from typing import Any
from functools import reduce


# enumerate() 函数
# 用于将`一个可遍历的数据对象`(如列表、元组或字符串)组合为一个索引序列, 同时列出数据和数据下标, 一般用在 for 循环当中
# enumerate(sequence, [start=0]): sequence -- 一个序列、迭代器或其他支持迭代对象; start -- 下标起始位置；返回 enumerate(枚举) 对象
# Python 2.3. 以上版本可用, 2.6 添加 start 参数
seasons: list = ['Spring', 'Summer', 'Fall', 'Winter']
print(list(enumerate(seasons)))  # [(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
print(list(enumerate(seasons, start=1)))  # 下标从1开始 [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

for index, value in enumerate(seasons):
    print(f"{index}: {value}")


# eval() 函数: 函数用来执行一个字符串表达式, 并返回表达式的值
# eval(expression, globals[, locals]])
# expression -- 表达式, globals -- 变量作用域, 全局命名空间, 如果被提供, 则必须是一个字典对象, 
# locals -- 变量作用域, 局部命名空间, 如果被提供, 可以是任何映射对象
# 返回表达式计算结果
x = 3
print(eval('3 * x'))  # 9
print(eval('pow(3, x)'))  # 27
print(eval('3 + 2'))  # 5

# bin()函数
# bin() 返回一个整数 int 或者长整数 long int 的二进制表示
print(bin(10))  # 0b 1010

# callable() 函数
# 用于检查一个对象是否是可调用的
def call():
    return 'ok'

class A:
    def __init__(self) -> None:
        pass

    def __call__(self, *args: Any, **kwds: Any) -> Any:
        pass

print(callable(0))  # False 未定义该方法或类
print(callable(A))  # True 类名

class B:
    def __init__(self) -> None:
        pass

    def __call__(self, *args: Any, **kwds: Any) -> Any:
        pass

b: B = B()
print(callable(b))  # False 没有实现 __call__

# reduce() 函数
# reduce() 函数会对参数序列中元素进行累积
# 函数将一个数据集合（链表, 元组等）中的所有数据进行下列操作
#     用传给 reduce 中的函数 function（有两个参数）先对集合中的第 1、2 个元素进行操作
#.    得到的结果再与第三个数据用 function 函数运算, 最后得到一个结果
# reduce(function, iterable[, initializer]): terable -- 可迭代对象, nitializer -- 可选, 初始参数
def reduces(n1, n2):
    return n1 + n2


print(reduce(reduces, [1, 2, 3, 4, 5]))  # python3已经移除reduce函数 - >15
print(reduce(lambda n1, n2: n1 + n2, [1, 2, 3, 4, 5]))  # 15


# getattr()、settattr() hasattr() 函数
class D:
    age = 18


d = D()
print(getattr(d, "age")) # 18

setattr(d, 'age', 25)
setattr(d, 'sex', 1)
print(d.age, d.sex)  # 25 1

print(hasattr(d, "sex")) # True
print(hasattr(d, "weight")) # False


# map() 会根据提供的函数对指定序列做映射
# map(function, iterable1, iterable2, iterable3,...): iterable -- 一个或多个序列(Python 3 返回迭代器)
list1: list = [1, 3, 5, 7, 9]
list2: list = [2, 4, 6]
list3: list = [10, 200, 300, 400, 500]

def mapfunc(num1: int, num2: int, num3: int) -> int:
    return num1 + num2 + num3

mapfunc(list1[0], list2[0], list3[0])
mapfunc(list1[1], list2[1], list3[1])
mapfunc(list1[2], list2[2], list3[2])

for i in map(mapfunc, list1, list2, list3):
    print(i)  # 13 207 311

# 特殊用法, 做类型转换
l5 = map(int, ["123", "456", "789", "1011"])
for i in l5:
    print(i, type(i))

# filter() 函数用于过滤序列, 过滤掉不符合条件的元素, 返回由符合条件元素组成的新列表
# 该接收两个参数, 第一个为函数, 第二个为序列, 序列的每个元素作为参数传递给函数进行判断, 然后返回 True 或 False, 最后将返回 True 的元素放到新列表中
# filter(function, iterable): function -- 判断函数, iterable -- 可迭代对象

# 过滤出1~100中平方根是整数的数
def is_sqrt(x):
    return math.sqrt(x) % 1 == 0

new_list = filter(is_sqrt, range(1, 101))
n16 = [i for i in new_list]
print(n16)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# zip() 函数 zip(*num)
# zip() 函数用于将可迭代的对象作为参数, 将对象中对应的元素打包成一个个元组, 然后返回由这些元组组成的列表
# 如果各个迭代器的元素个数不一致, 则返回列表长度与最短的对象相同, 利用 * 号操作符, 可以将元组解压为列表

# zip(*num): 可理解为解压, 返回二维矩阵式
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9, 10, 12]
n9 = zip(a, b)
n10 = [i for i in n9]
print(n10)  # [(1, 4), (2, 5), (3, 6)]
zipped = zip(*n10)
print([i for i in zipped])  # [(1, 2, 3), (4, 5, 6)]

# round() 函数
# round() 方法返回浮点数x的四舍五入值
# round( x [, n]  ): x -- 数值表达式, n -- 数值表达式, 表示从小数点位数
print(round(80.23856, 2))  # 80.24

# ord()函数: A-Z 65-90, a-z 97-122
# ord() 函数是 chr() 函数（对于8位的ASCII字符串）或 unichr() 函数（对于Unicode对象）的配对函数, 它以一个字符（长度为1的字符串）作为参数, 返回对应的 ASCII 数值
# 或者 Unicode 数值, 如果所给的 Unicode 字符超出了你的 Python 定义范围, 则会引发一个 TypeError 的异常
c = 'a'
print(ord(c))  # 97
c = 'A'
print(ord(c))  # 65

# chr() 函数: 返回 unicode 的字符
print(chr(97))  # a
print(chr(100))  # d

# any()函数
# any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False, 则返回 False, 如果有一个为 True, 则返回 True
# any(iterable)
# iterable -- 元组或列表, 如果都为空、0、false, 则返回false, 如果不都为空、0、false, 则返回true
print(any(['a', 'b', 'c', 'd']))  # 列表list, 元素都不为空或0) -> True
print(any((0, '', False)))  # 元组tuple, 元素都为空或0、False -> False
print(any(['a', 'b', '', 'd']))  # 列表list, 元素存在为空或0、False -> True

# divmod
# 把除数和余数运算结果结合起来, 返回一个包含商和余数的元组(a // b, a % b)
print(divmod(7, 2))  # (3, 1)
print(divmod(7, 2)[0])  # 3
